package com.ihy.domain;

import lombok.*;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
import org.hibernate.annotations.GenericGenerator;
import org.springframework.stereotype.Component;

import javax.persistence.*;
import java.io.Serializable;
import java.util.Set;

/**
 * 角色表实体类
 * Entity注解：
 * 指定类是实体。此注解应用于实体类。
 * <p>
 * Table注解:
 * 指定带注解实体的主表。可以使用SecondaryTable或SecondaryTables注解指定其他表。
 * 如果没有为实体类指定表注解，则应用默认值。
 * <p>
 * Getter注解:
 * 创建当前实体类所有的get方法
 * <p>
 * Setter注解:
 * 创建当前实体类所有的set方法
 * <p>
 * ToString注解:
 * 创建当前实体类所有属性的toString方法
 * <p>
 * AllArgsConstructor注解：
 * 生成all args构造函数。all args构造函数要求类中的每个字段都有一个参数。
 * <p>
 * NoArgsConstructor注解：
 * 生成无参数构造函数。如果由于final字段的存在而无法编写此类构造函数，则将生成错误消息。
 * <p>
 * Component注解：
 * 指示带注解的类是“组件”。当使用基于注解的配置和类路径扫描时，这些类被认为是自动检测的候选类。
 * 其他类级注解也可以被视为标识组件，通常是一种特殊类型的组件：例如@Repository注解或AspectJ的@Aspect注解。
 */
@Entity
@Table(name = "role")
@Getter
@Setter
@ToString
@AllArgsConstructor
@NoArgsConstructor
@Component
public class Role implements Serializable {

    /**
     * Id注解：
     * 指定实体的主键。应用Id注解的字段或属性应该是以下类型之一：任何Java基元类型；任何基元包装类型；字符串；日期类型; java.sql.Date日期; java.math.BigDecimal文件; java.math.BigInteger文件.
     * 假定实体主键的映射列是主表的主键。如果未指定列注解，则假定主键列名是主键属性或字段的名称。
     */
    @Id
    //以泛型（反类型化）方式描述任何类型的Hibernate生成器的生成器注解
    @GenericGenerator(name = "pk", strategy = "increment")
     /*
     GeneratedValue注解：
     提供主键值的生成策略的规范。
     GeneratedValue注解可与Id注解一起应用于实体或映射超类的主键属性或字段。
     仅要求简单主键支持使用GeneratedValue注解。派生主键不支持使用GeneratedValue注解。

     Column注解：
     指定持久属性或字段的映射列。如果未指定列注解，则应用默认值。
     */
    @GeneratedValue(generator = "pk")
    @Column(name = "id")
    private int id;
    @Column(name = "name")
    private String name;
    /*
    一对多关系 (Role vs Jurisdiction)

    OneToMany注解：
    指定具有一对多 多重性的多值关联。
    如果使用泛型定义集合以指定元素类型，则无需指定关联的目标实体类型；否则必须指定目标实体类。
    如果关系是双向的，则必须使用mappedBy元素指定作为关系所有者的实体的关系字段或属性。
    OneToMany注解可以在实体类中包含的可嵌入类中使用，以指定与实体集合的关系。
    当集合是java.util.Map文件，cascade元素和orninRemoval元素应用于映射值。

    Fetch注解：
    定义用于给定关联的获取策略。

    JoinTable注解：
    指定关联的映射。它应用于关联的拥有方。
    联接表通常用于多对多和单向一对多关联的映射。它还可用于映射双向多对一/一对多关联、单向多对一关系和一对一关联（双向和单向）。
    当连接表用于将关系映射到关系所属方的可嵌入类时，包含实体而不是可嵌入类被视为关系的所有者。
    如果缺少JoinTable注解，则应用注解元素的默认值。联接表的名称假定为使用下划线连接在一起的关联主表的表名（首先是拥有方）。

    JoinColumn注解：
    指定用于连接实体关联或元素集合的列。如果JoinColumn注解本身为默认值，则假定为单个连接列，并应用默认值。
    */
    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    @Fetch(FetchMode.SELECT)
    //中间表名,当前对象id在中间表的列名,关联的另一个表在中间表的列名
    @JoinTable(name = "rj", joinColumns = {@JoinColumn(name = "roleid")}, inverseJoinColumns = {@JoinColumn(name = "jurisdictionid")})
    private Set<Jurisdiction> jurisdictions;
}
